/* ****************************************************************************
 *
 * Copyright (c) Microsoft Corporation. 
 *
 * This source code is subject to terms and conditions of the Microsoft Public License. A 
 * copy of the license can be found in the License.html file at the root of this distribution. If 
 * you cannot locate the  Microsoft Public License, please send an email to 
 * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound 
 * by the terms of the Microsoft Public License.
 *
 * You must not remove this notice, or any other, from this software.
 *
 * THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
 * KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
 * PARTICULAR PURPOSE.
 * ***************************************************************************/


#if !defined(AFX_EPSINTERFACE_H__C35451D2_234F_4CA2_84C3_D860EA95D014__INCLUDED_)
#define AFX_EPSINTERFACE_H__C35451D2_234F_4CA2_84C3_D860EA95D014__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include <pgl/igfx/FileGfxInterface.h>

namespace gfxinterface
{

/*! \brief Class to create EPS files

  \ingroup IGfxGroup

	This class is designed to create your own eps files.
*/
class CEPSInterface : public CFileGfxInterface  
{
protected:
	//! A structure describing a linear gradient.
	struct SEPSLinearGradient
	{
		SRGBA m_cStart;
		SRGBA m_cEnd;
		SPointD m_pStart;
		SPointD m_pEnd;
	};
	
	/*! \brief Acutal eps state
	
	  \ingroup IGfxStruct
	This structure is used internaly in CEPSWriter to keep track of the current postscript graphic state.
	The following states are tracked:
	<ul>
	<li>color components, RGB,
	<li>line width,
	<li>line dashing.
	</ul>
	*/
	struct SEPSState
	{
		//! types of fills
		static enum EFillType	
		{	
			//! plain color
			SolidFill=0, 
			//! linear gradient
			LinearGradientFill=1
		};
		//! fill type
		EFillType m_eFillType;
		//! stroke color
		SRGBA strokecol;
		//! solid fill color
		SRGBA fillcol;
		//!linear gradient
		SEPSLinearGradient m_sLinearGradient;
		//! fill color
		SRGBA m_cShadow;
		//! current linewidth
		double linewidth;		
		//! current dash style
		std::_tstring dash;
		//! current font
		LOGFONT font;
	};

	//! Pile of graphic states
	typedef std::list<SEPSState> EPSStatePile;

public:
	CEPSInterface();
	virtual ~CEPSInterface();

	virtual void BeginPaint(HDC hDC );
	virtual void EndPaint();

	virtual void AddComment(LPCTSTR str);

	virtual void PushClipWorld(double llx, double lly, double urx, double ury);
	virtual void PopClipWorld();
	virtual void PushState();
	virtual void PopState();

	virtual void DrawGridHor(double llx, double urx, double lly, double ury,double dy);
	virtual void DrawGridVer(double llx, double urx, double lly, double ury,double dx);

	virtual void SetColor(double r, double g, double b, double a = 1);
	virtual void SetFillColor(double r, double g, double b, double a = 1);
	virtual void SetLinearGradientFill(const SPointD& point1, const SPointD& point2, const SRGBA& col1, const SRGBA& col2);
	virtual void SetShadowColor(double r, double g, double b, double a = 0.2);
	virtual void SetLineWidth(double width);	
	virtual void SetDash(LPCTSTR dash);

	virtual void DrawRect(double llx, double lly, double urx, double ury, DWORD dwRectFlag = 0 , SPointD sShadowSize = SPointD(0,0));
	virtual void DrawArrow(double tailx, double taily, double tipx, double tipy, double tailthickness, double  headthickness, double headlength, bool filled =true);
	virtual void DrawArrowAbs(double tailx, double taily, double dtipx, double dtipy, double tailthickness, double  headthickness, double headlength, bool filled =true);
	virtual void DrawLine(double x1, double y1, double x2, double y2);

	virtual void DrawLineStrip(const CVectorF& vX, const CVectorF& vY, DWORD eLineTypeFlag =0 , double dTension=0);
	virtual void DrawStepStrip(const CVectorF& vX, const CVectorF& vY, DWORD eLineTypeFlag =0 );
	virtual void DrawBandStrip(const CVectorF& vX, const CVectorF& vYBottom, const CVectorF& vYTop, DWORD eBandTypeFlag = 0, double dTension=0);
	virtual void DrawMultipleLineStrip(int ns, const CVectorF& vX, const CVectorF& vY, DWORD eLineTypeFlag =0 );

	virtual void DrawStock( double x0, double dx, const CVectorF& vHis, const CVectorF& vLows, const CVectorF& vOpens, const CVectorF& vCloses, const SRGBA& cDownColor, DWORD eStockTypeFlag = 0);
	virtual void DrawErrorBars( const CVectorF& vXs,  const CVectorF& vYs,const CVectorF& vUps, const CVectorF& vDowns, double dWidth, bool bAbsolute = true, bool bVertical = true);

	virtual void DrawCircle(double cx, double cy, double radius, DWORD eLineType = LineTypeClosed);
	virtual void DrawPolygon(double cx, double cy,  const CVectorF& vPx, const CVectorF& vPy, DWORD eLineType = LineTypeClosed);

	virtual void DrawCircleStrip(const CVectorF& vCx, const CVectorF& vCy, double dRadius, DWORD eLineType = LineTypeClosed);
	virtual void DrawPolygonStrip(const CVectorF& vCx, const CVectorF& vCy,  const CVectorF& vPx, const CVectorF& vPy, DWORD eLineType = LineTypeClosed);

	virtual void SetFont(const LOGFONT& logFont);
	virtual void DrawText(double x, double y, LPCTSTR str, ETextAlignment ta = TextAlignmentLeft, double angle = 0);
	virtual void DrawTextStrip(const std::vector<SPointD>& vPoints, const std::vector<std::_tstring>& vStrings, ETextAlignment ta = TextAlignmentCenter, double angle = 0);

	//! \arc functions
	//@{
	void DrawArc(double cnx, double cny, double rn, double angle, double aperture, double rep, DWORD flags){};
	//@}

	virtual void DrawSurf(const contour::TLattice<float>& tLattice, const CVectorF& vColor, DWORD dwFlag=0);
	virtual void DrawVectorField(const contour::TLattice<float>& tLattice, const CVectorF& vVx, const CVectorF& vVy, float fScale=1, DWORD dwFlags=0);

	virtual double BBToWorldx(double x) const		{	return GetWorldLeft()+(x-(double)GetBBLeft())/(double)(GetBBWidth())*(double)(GetWorldWidth());};
	virtual double BBToWorldy(double y) const		{	return GetWorldBottom()+(y-(double)GetBBBottom())/(double)(GetBBHeight())*(double)(GetWorldHeight());};
	virtual double BBToWorldAbsx(double x) const	{	return x/(double)(GetBBWidth())*(double)(GetWorldWidth());};
	virtual double BBToWorldAbsy(double y) const	{	return y/(double)(GetBBHeight())*(double)(GetWorldHeight());};

	//! Transform world x coordinate to file coordinate x
	virtual double WorldToBBx(double x) const		{	return GetBBLeft()+(x-(double)GetWorldLeft())/(double)(GetWorldWidth())*(double)(GetBBWidth());};
	//! Transform world y coordinate to file coordinate y
	virtual double WorldToBBy(double y) const		{	return GetBBBottom()+(y-(double)GetWorldBottom())/(double)(GetWorldHeight())*(double)(GetBBHeight());};

	//! Transform world x coordinate to file coordinate x
	virtual double WorldToBBAbsx(double x) const	{	return x/(double)(GetWorldWidth())*(double)(GetBBWidth());};
	//! Transform absolute world y coordinate to file coordinate y
	virtual double WorldToBBAbsy(double y) const	{	return y/(double)(GetWorldHeight())*(double)(GetBBHeight());};
	//! Save EPS file and writes header
	virtual LPCTSTR GetFileExt() const				{	return _T("eps");};
	void Fill();

protected:
	void PutStrokeColorString();
	void PutFillColorString();
	void DefinePolygon(const CVectorF& vx, const CVectorF& vy, DWORD eLineType);
	void DefineCircle(double dRadius, DWORD eLineType);
	void InitState();
	virtual void WriteHeader();
private:
	SEPSState m_state;
	EPSStatePile m_lStates;
};

}
#endif // !defined(AFX_EPSINTERFACE_H__C35451D2_234F_4CA2_84C3_D860EA95D014__INCLUDED_)
